Skip to main content

Internal Memory

When we talk about "internal memory" in Go (or any language), we’re referring to how data is stored and managed in the computer’s RAM while the program runs.

Go divides internal memory into several important areas:

  1. Stack – Small, fast memory used for function calls and local variables.
  2. Heap – Larger memory area used for dynamically allocated variables.
  3. Data Segment – For global and static variables.
  4. Code Segment – Where compiled machine instructions are stored.

Memory Layout

When a Go program runs, memory is roughly divided like this:

+---------------------+   <- High memory addresses
| Command Line Args |
+---------------------+
| Environment Vars |
+---------------------+
| Stack | <- Each goroutine has its own stack
+---------------------+
| Heap | <- Shared between all goroutines
+---------------------+
| Global Variables |
+---------------------+
| Program Code |
+---------------------+ <- Low memory addresses

Stack

  • Stores function call frames:
    • Local variables
    • Function parameters
    • Return addresses
  • Automatically cleaned up after a function returns.
  • Very fast because it works like a LIFO (Last In, First Out) structure.
  • Limited in size (default goroutine stack starts small, grows automatically).
func add(a, b int) int {
result := a + b // 'result' stored on stack
return result
}

func main() {
sum := add(5, 3) // 'sum' stored on stack
fmt.Println(sum)
}
  • a, b, and result live in the stack frame of add().
  • sum lives in the stack frame of main().

Heap

  • Stores dynamically allocated memory.
  • Managed by Go’s garbage collector.
  • Slower than stack, but size is much bigger.
  • Memory stays allocated until garbage collector removes it.
func createSlice() *[]int {
nums := []int{1, 2, 3} // allocated on heap
return &nums
}

func main() {
slicePtr := createSlice()
fmt.Println(*slicePtr)
}
  • nums escapes to the heap because we return a pointer to it.
  • Even after createSlice() ends, nums stays in memory (heap) until GC clears it.

Data Segment

  • Stores global variables and constants.
  • Exists for the entire lifetime of the program
var globalCount int = 100 // stored in data segment

func main() {
fmt.Println(globalCount)
}
  • globalCount is stored in a fixed memory location in the data segment.

Code Segment

  • Stores the compiled binary instructions of your Go program.
  • Read-only for safety.
  • Rarely manipulated directly by Go developers.

Stack vs Heap

FeatureStackHeap
SpeedFastSlower
SizeSmall, grows per goroutineLarge
LifetimeUntil function endsUntil GC cleans it
ManagementAutomatic (LIFO)Garbage Collector
Best forLocal, short-lived variablesLong-lived, shared data

Memory Escape

Go decides where variables go (stack or heap) at compile time. If a variable “escapes” a function (returned or referenced externally), it goes to the heap.

func heapExample() *int {
x := 42
return &x // escapes to heap
}

func stackExample() int {
x := 42
return x // stays in stack
}

func main() {
heapPtr := heapExample()
fmt.Println(*heapPtr)

stackVal := stackExample()
fmt.Println(stackVal)
}